package br.com.persistencia;

import br.com.excecoes.DAOException;
import br.com.persistence.util.ExceptionsType;
import java.lang.reflect.ParameterizedType;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import org.hibernate.Criteria;
import org.hibernate.Session;
import sun.rmi.runtime.Log;

/**
 *
 * @author Gernan
 */
public abstract class DaoGenericImpl<T> implements DaoGeneric<T> {

    private Class classe;

    public DaoGenericImpl() {
        this.classe = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
    }

    @Override
    public T save(T t) throws DAOException {
        EntityManager manager = PersistenceUtil.getEntityManager();
        try {
            manager.getTransaction().begin();
            manager.persist(t);
            manager.getTransaction().commit();
            manager.refresh(t);
            return t;
        } catch (Exception e) {
            manager.getTransaction().rollback();
            throw new DAOException(ExceptionsType.getMessage(ExceptionsType.INSERT_ERROR), e);
        } finally {
            manager.close();
        }
    }

    @Override
    public T update(T t) throws DAOException {
        EntityManager manager = PersistenceUtil.getEntityManager();
        try {
            manager.getTransaction().begin();
            manager.merge(t);
            manager.getTransaction().commit();
            return t;
        } catch (Exception e) {
            manager.getTransaction().rollback();
            throw new DAOException(ExceptionsType.getMessage(ExceptionsType.UPDATE_ERROR), e);
        } finally {
            manager.close();
        }
    }

    @Override
    public T remove(T t) throws DAOException {
        EntityManager manager = PersistenceUtil.getEntityManager();
        try {
            manager.getTransaction().begin();
            t = manager.merge(t);
            manager.remove(t);
            manager.getTransaction().commit();
            return t;
        } catch (Exception e) {
            manager.getTransaction().rollback();
            throw new DAOException(ExceptionsType.getMessage(ExceptionsType.REMOVE_ERROR), e);
        } finally {
            manager.close();
        }
    }

    @Override
    public List<T> getAll() throws DAOException {
        List<T> resultado = null;
        EntityManager manager = PersistenceUtil.getEntityManager();
        try {
            Session session = (Session) manager.getDelegate();
            session.clear();
            resultado = session.createCriteria(classe).list();
            return resultado;
        } catch (Exception e) {
            manager.getTransaction().rollback();
            throw new DAOException(ExceptionsType.getMessage(ExceptionsType.READ_ERROR), e);
        } finally {
            manager.close();
        }
    }

    @Override
    public Criteria getCriteria() throws DAOException {
        EntityManager manager = PersistenceUtil.getEntityManager();
        Session session = ((Session) manager.getDelegate());
        session.clear();
        return session.createCriteria(classe);
    }

    @Override
    public Session getSession() throws DAOException {
        EntityManager manager = PersistenceUtil.getEntityManager();
        Session session = ((Session) manager.getDelegate());
        session.clear();
        return session;
    }

    @Override
    public T executeNativeQuerySingleResult(String sql) throws DAOException {
        T resultado = null;
        EntityManager manager = PersistenceUtil.getEntityManager();
        try {
            Query query = manager.createNativeQuery(sql, classe);
            resultado = (T) query.getSingleResult();
            return resultado;
        } catch (Exception e) {
            throw new DAOException(ExceptionsType.getMessage(ExceptionsType.READ_ERROR), e);
        } finally {
            manager.close();
        }
    }

    @Override
    public List<T> executeNativeQueryMultiResult(String sql) throws DAOException {
        List<T> resultado = null;
        EntityManager manager = PersistenceUtil.getEntityManager();
        try {
            Query query = manager.createNativeQuery(sql, classe);
            resultado = (List<T>) query.getResultList();
            return resultado;
        } catch (Exception e) {
            throw new DAOException(ExceptionsType.getMessage(ExceptionsType.READ_ERROR), e);
        } finally {
            manager.close();
        }
    }
}